﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Styx.WoWInternals;
using Styx.Common;
using System.Windows.Media;

using Styx;
using Styx.WoWInternals.WoWObjects;
using Styx.CommonBot;
using Styx.CommonBot.Coroutines;

using units = Paster.Managers.Units;
using spells = Paster.Spell.Spells;
using SD = Paster.GUI.DiscSettings;
using Movement = Paster.Managers.Movement;
using CP = Paster.GUI.CommonSettings;
using groups = Paster.Managers.Groups;

namespace Paster.Disc
{
    partial class Rotation
    {

        private static LocalPlayer Me { get { return StyxWoW.Me; } }

        public static DateTime buffTimer;


        #region keep PWS on tank
        public static bool KeepPwsOnTank()
        {
            if (!SD.myPrefs.KeepPWSonTank) return false;
            return true;
        }
        public static WoWUnit tankPws
        {
            get
            {
                if (groups.partyCount == 0 && !units.buffExists(spells.PowerWordShield, Me)
                && !units.debuffExists(spells.weakenedsoul, Me)
                && !units.spellOnCooldown(spells.PowerWordShield))
                {
                    return Me;
                }
                if (groups.partyCount > 0 && InProvingGrounds)
                {
                    var t = groups.PartyMembers.Where(p => p.Name == "Oto the Protector").FirstOrDefault();;
                    if (t != null
                        && t.HealthPercent > 0
                        && t.InLineOfSight
                        && t.Distance < 40
                        && !units.buffExists(spells.PowerWordShield, t)
                        && !units.debuffExists(spells.weakenedsoul, t)
                        && !units.spellOnCooldown(spells.PowerWordShield))
                    {
                        return t;
                    }
                    return null;

                }
                if (groups.partyCount > 0 && !InProvingGrounds)
                {
                    var t = groups.Tanks.Where(p => p != null
                        && p.HealthPercent > 1
                        && p.InLineOfSight
                        && p.Distance < 40
                        && !units.buffExists(spells.PowerWordShield, p)
                        && !units.debuffExists(spells.weakenedsoul, p)).OrderBy(p => p.HealthPercent).FirstOrDefault();
                    return t != null ? t : null;
                }
                return null;
            }
        }
        #endregion

        #region power word fortitude
        public static bool needFortitude()
        {
            if (Me.Mounted || units.buffExists("Food", Me) || units.buffExists("Drink", Me)) return false;
            if (CP.myPrefs.fortitude == CP.powerwordfortitude.Manual) return false;
            if (CP.myPrefs.fortitude == CP.powerwordfortitude.ForAllPartyMembers) return false;
            if (DateTime.Now <= buffTimer) return false;
            if (units.buffExists(spells.PowerWordFortitude, Me) && CP.myPrefs.fortitude == CP.powerwordfortitude.OnlyOnMyself) return false;
            buffTimer = DateTime.Now + new TimeSpan(0, 0, 0, 0, 1000);
            return true;
        }
        public static bool needFortitudeAll()
        {
            if (CP.myPrefs.fortitude != CP.powerwordfortitude.ForAllPartyMembers) return false;
            var t = groups.PartyMembers.Where(p => p.IsAlive
                 && p.Distance <= 40
                 && p.InLineOfSight
                 && !units.buffExists(spells.PowerWordFortitude, p)).FirstOrDefault();
            return t != null ? true : false;
        }
        #endregion

        #region atonement
        public static bool healerAloneIsMe
        {
            get
            {
                if (groups.partyCount == 0) return false;

                var t = new List<WoWUnit>();
                t = groups.PartyMembers.Where(p => p.IsAlive).ToList();
                if (t.Count() == 1 && t.FirstOrDefault().IsMe) return true;
                return false;
            }
        }


        public static bool needAtonement()
        {
            if (groups.partyCount > 0 && healerAloneIsMe) return true;
            if (groups.partyCount > 0 && SD.myPrefs.Atonement && Me.ManaPercent > SD.myPrefs.AtonementManaPercent && dpsTarget != null) return true;
            return false;
        }
        #endregion

        #region healthstone
        public static int healthstonePercent = SD.myPrefs.HealthstonePercent;
        public static int healthStone = 5512;
        public static bool needHealthstone()
        {
            return Me.HealthPercent <= healthstonePercent;
        }
        #endregion

        #region need power word solace
        public static bool needPowerWordSolace()
        {
            if (!SpellManager.HasSpell(spells.PowerWordSolace)) return false;
            if (dpsTarget != null && !units.spellOnCooldown(spells.PowerWordSolace)) return true;

            return false;
        }
        #endregion

        #region dpstargets

        public static WoWUnit dpsTarget
        {
            get
            {
                if (groups.partyCount == 0 && Me.CurrentTarget != null && units.ValidUnit(Me.CurrentTarget)) return Me.CurrentTarget;
                if (Me.CurrentTarget != null 
                    && units.ValidUnit(Me.CurrentTarget)
                    && Me.CurrentTarget.Distance <= 40
                    && Me.IsSafelyFacing(Me.CurrentTarget)) { return Me.CurrentTarget; }
                else
                {
                    var t = new List<WoWUnit>();

                    t = ObjectManager.GetObjectsOfTypeFast<WoWUnit>().Where(p => p.IsAlive
                        && p.IsHostile
                        && (p.Combat
                        && (p.IsTargetingMeOrPet || p.IsTargetingMyPartyMember || p.IsTargetingMyRaidMember))
                        && p.InLineOfSight
                        && p.Distance <= 40
                        && Me.IsSafelyFacing(p)).OrderBy(p => p.Distance).ToList();
                    return t.Count() > 0 ? t.FirstOrDefault() : null;
                }
            }
        }

        public static bool needFearWard()
        {
            if (!SD.myPrefs.FearWardAuto) return false;
            if (SD.myPrefs.FearWardAuto && !units.buffExists(spells.FearWard, Me) && !units.spellOnCooldown(spells.FearWard)) { return true; }
            return false;
        }
        #endregion

        #region tanks, healer, dps
        public static bool InProvingGrounds { get { return Me.MinimapZoneText == "Proving Grounds"; } }

        public static bool needPowerInfusion()
        {
            int healthCheck = SD.myPrefs.PowerInfusionPlayerHP;
            int playerCount = SD.myPrefs.PowerInfusionPlayerCount;
            int mana = SD.myPrefs.PowerInfusionManapercent;

            if (!SpellManager.HasSpell(spells.PowerInfusion)) { return false; }
            if (!SD.myPrefs.PowerInfusionAuto) { return false; }
            if (Me.ManaPercent <= mana && !units.spellOnCooldown(spells.PowerInfusion)) { return true; }

            var t = new List<WoWUnit>();
            t = groups.PartyMembers.Where(p => p.IsAlive
                && p.InLineOfSight
                && p.Distance <= 40
                && p.HealthPercent <= healthCheck).ToList();

            if (t.Count() >= playerCount && !units.spellOnCooldown(spells.PowerInfusion)) { return true; }
            return false;
        }

        public static bool needPenanceDps()
        {
            if (SD.myPrefs.AtonementPenance
                && SD.myPrefs.Atonement
                && Me.ManaPercent > SD.myPrefs.AtonementManaPercent
                && !units.spellOnCooldown(spells.Penance))
            {
                return true;
            }
            return false;
        }

        public static WoWUnit targetToHeal = null;

        public static bool needArchangel()
        {
            return spells.IsOverlayed(spells.Archangel);
        }

        public static WoWUnit pwsUnit
        {
            get
            {
                int healthCheck = SD.myPrefs.PWSD;
                if (groups.partyCount > 6) healthCheck = SD.myPrefs.PWSR;

                if (groups.partyCount == 0 && Me.HealthPercent <= healthCheck && !units.buffExists(spells.PowerWordShield, Me)
                    && !units.debuffExists(spells.weakenedsoul, Me) && !units.spellOnCooldown(spells.PowerWordShield))
                {
                    return Me;
                }
                if (InProvingGrounds)
                {
                    var t = groups.PartyMembers.Where(p => p.IsAlive
                        && p.InLineOfSight
                        && p.Distance <= 40
                        && !units.buffExists(spells.PowerWordShield, p)
                        && !units.debuffExists(spells.weakenedsoul, p)
                        && p.HealthPercent <= healthCheck).OrderBy(p => p.HealthPercent).FirstOrDefault();
                    if (t != null && !units.spellOnCooldown(spells.PowerWordShield))
                    {
                        return t;
                    }
                    return null;
                }
                if (groups.partyCount > 0 && !InProvingGrounds)
                {
                    var t = groups.PartyMembers.Where(p => p != null
                        && p.IsAlive
                        && p.InLineOfSight
                        && p.Distance <= 40
                        && !units.buffExists(spells.PowerWordShield, p)
                        && !units.debuffExists(spells.weakenedsoul, p)
                        && p.HealthPercent <= healthCheck).OrderBy(p => p.HealthPercent).FirstOrDefault();
                    if (t != null && !units.spellOnCooldown(spells.PowerWordShield))
                    {
                        return t;
                    }
                    return null;
                }
                return null;
            }
        }
        public static WoWUnit flashUnit
        {
            get
            {
                int healthCheck = SD.myPrefs.FlashD;
                if (groups.partyCount > 6) healthCheck = SD.myPrefs.FlashR;

                if (groups.partyCount == 0 && Me.HealthPercent <= healthCheck)
                {
                    return Me;
                }
                if (InProvingGrounds)
                {
                    var t = groups.PartyMembers.Where(p => p != null
                        && p.IsAlive
                        && p.InLineOfSight
                        && p.Distance <= 40
                        && p.HealthPercent <= healthCheck).OrderBy(p => p.HealthPercent).FirstOrDefault();
                    if (t != null)
                    {
                        return t;
                    }
                    return null;
                }
                if (groups.partyCount > 0 && !InProvingGrounds)
                {
                    var t = groups.PartyMembers.Where(p => p != null
                        && p.IsAlive
                        && p.InLineOfSight
                        && p.Distance <= 40
                        && p.HealthPercent <= healthCheck).OrderBy(p => p.HealthPercent).FirstOrDefault();
                    if (t != null)
                    {
                        return t;
                    }
                    return null;
                }
                return null;
            }
        }
        public static WoWUnit penanceUnit
        {
            get
            {
                int healthCheck = SD.myPrefs.PenanceD;
                if (groups.partyCount > 6) healthCheck = SD.myPrefs.PenanceR;

                if (groups.partyCount == 0 && Me.HealthPercent <= healthCheck && !units.spellOnCooldown(spells.Penance))
                {
                    return Me;
                }
                if (InProvingGrounds)
                {
                    var t = groups.PartyMembers.Where(p => p != null
                        && p.IsAlive
                        && p.InLineOfSight
                        && p.Distance <= 40
                        && p.HealthPercent <= healthCheck).OrderBy(p => p.HealthPercent).FirstOrDefault();
                    if (t != null && !units.spellOnCooldown(spells.Penance))
                    {
                        return t;
                    }
                    return null;
                }
                if (groups.partyCount > 0 && !InProvingGrounds)
                {
                    var t = groups.PartyMembers.Where(p => p != null
                        && p.IsAlive
                        && p.InLineOfSight
                        && p.Distance <= 40
                        && p.HealthPercent <= healthCheck).OrderBy(p => p.HealthPercent).FirstOrDefault();
                    if (t != null && !units.spellOnCooldown(spells.Penance))
                    {
                        return t;
                    }
                    return null;
                }
                return null;
            }
        }
        public static WoWUnit healUnit
        {
            get
            {
                int healthCheck = SD.myPrefs.HealD;
                if (groups.partyCount > 6) healthCheck = SD.myPrefs.HealR;

                if (groups.partyCount == 0)
                {
                    return null;
                }
                if (InProvingGrounds)
                {
                    var t = groups.PartyMembers.Where(p => p != null
                        && p.IsAlive
                        && p.InLineOfSight
                        && p.Distance <= 40
                        && p.HealthPercent <= healthCheck).OrderBy(p => p.HealthPercent).FirstOrDefault();
                    if (t != null)
                    {
                        return t;
                    }
                    return null;
                }
                if (groups.partyCount > 0 && !InProvingGrounds)
                {
                    var t = groups.PartyMembers.Where(p => p != null
                        && p.IsAlive
                        && p.InLineOfSight
                        && p.Distance <= 40
                        && p.HealthPercent <= healthCheck).OrderBy(p => p.HealthPercent).FirstOrDefault();
                    if (t != null)
                    {
                        return t;
                    }
                    return null;
                }
                return null;
            }
        }
        public static WoWUnit pomUnit
        {
            get
            {
                int healthCheck = SD.myPrefs.PomD;
                if (groups.partyCount > 6) healthCheck = SD.myPrefs.PomR;

                if (groups.partyCount == 0)
                {
                    return null;
                }
                if (InProvingGrounds)
                {
                    var t = groups.PartyMembers.Where(p => p != null
                        && p.IsAlive
                        && p.InLineOfSight
                        && p.Distance <= 40
                        && p.HealthPercent <= healthCheck).OrderBy(p => p.HealthPercent).FirstOrDefault();
                    if (t != null && !units.spellOnCooldown(spells.PrayerofMending))
                    {
                        return t;
                    }
                    return null;
                }
                if (groups.partyCount > 0 && !InProvingGrounds)
                {
                    var t = groups.PartyMembers.Where(p => p != null
                        && p.IsAlive
                        && p.InLineOfSight
                        && p.Distance <= 40
                        && p.HealthPercent <= healthCheck).OrderBy(p => p.HealthPercent).FirstOrDefault();
                    if (t != null && !units.spellOnCooldown(spells.PrayerofMending))
                    {
                        return t;
                    }
                    return null;
                }
                return null;
            }
        }
        public static WoWUnit painUnit
        {
            get
            {
                int healthCheck = SD.myPrefs.PainTankD;
                if (groups.partyCount > 6) healthCheck = SD.myPrefs.PainTankR;

                if (groups.partyCount == 0)
                {
                    return null;
                }
                if (InProvingGrounds)
                {
                    var t = groups.PartyMembers.Where(p => p != null
                        && p.Name == "Oto the Protector"
                        && p.IsAlive
                        && p.InLineOfSight
                        && p.Distance <= 40
                        && p.HealthPercent <= healthCheck).FirstOrDefault();
                    if (t != null && !units.spellOnCooldown(spells.PainSuppression))
                    {
                        return t;
                    }
                    return null;
                }
                if (groups.partyCount > 0 && !InProvingGrounds)
                {
                    var t = new List<WoWPlayer>();
                    t = groups.Tanks.Where(p => p != null
                        && p.IsAlive
                        && p.InLineOfSight
                        && p.Distance <= 40
                        && p.HealthPercent <= healthCheck).Select(p => p.ToPlayer()).OrderBy(p => p.ToPlayer().HealthPercent).ToList();
                    if (t.Count() > 0 && !units.spellOnCooldown(spells.PainSuppression))
                    {
                        return t.FirstOrDefault();
                    }
                    return null;
                }
                return null;
            }
        }
        public static WoWUnit pohUnit
        {
            get
            {
                int healthCheck = SD.myPrefs.PoHD;
                if (groups.partyCount > 6) healthCheck = SD.myPrefs.PoHR;
                int playerCount = SD.myPrefs.PoHPlayerCountD;
                if (groups.partyCount > 6) playerCount = SD.myPrefs.PoHPlayerCountR;

                if (groups.partyCount == 0)
                {
                    return null;
                }
                if (InProvingGrounds)
                {
                    var t = new List<WoWUnit>();
                    t = groups.PartyMembers.Where(p => p != null
                        && p.IsAlive
                        && p.InLineOfSight
                        && p.Distance <= 40
                        && p.HealthPercent <= healthCheck).ToList();
                    if (t.Count() >= playerCount)
                    {
                        return t.FirstOrDefault();
                    }
                    return null;
                }
                if (groups.partyCount > 0 && !InProvingGrounds)
                {
                    var t = new List<WoWPlayer>();
                    t = groups.PartyMembers.Where(p => p != null
                        && p.IsAlive
                        && p.InLineOfSight
                        && p.Distance <= 40
                        && p.HealthPercent <= healthCheck).Select(p => p.ToPlayer()).OrderBy(p => p.ToPlayer().HealthPercent).ToList();
                    if (t.Count() >= playerCount)
                    {
                        return t.FirstOrDefault();
                    }
                    return null;
                }
                return null;
            }
        }
        public static WoWUnit cascadeUnit
        {
            get
            {
                int healthCheck = SD.myPrefs.CascadeHealthPercentD;
                if (groups.partyCount > 6) healthCheck = SD.myPrefs.CascadeHealthPercentR;
                int playerCount = SD.myPrefs.CascadePlayerCountD;
                if (groups.partyCount > 6) playerCount = SD.myPrefs.CascadePlayerCountR;
                if (groups.partyCount == 0)
                {
                    return null;
                }
                if (InProvingGrounds)
                {
                    var t = new List<WoWUnit>();
                    t = groups.PartyMembers.Where(p => p != null
                        && p.IsAlive
                        && p.InLineOfSight
                        && p.Distance <= 40
                        && p.HealthPercent <= healthCheck).OrderBy(p => p.HealthPercent).ToList();
                    if (t.Count() >= playerCount && !units.spellOnCooldown(spells.Cascade))
                    {
                        return t.FirstOrDefault();
                    }
                    return null;
                }
                if (groups.partyCount > 0 && !InProvingGrounds)
                {
                    var t = groups.PartyMembers.Where(p => p != null
                        && p.IsAlive
                        && p.InLineOfSight
                        && p.Distance <= 40
                        && p.HealthPercent <= healthCheck).OrderBy(p => p.HealthPercent).FirstOrDefault();
                    if (t != null && !units.spellOnCooldown(spells.Cascade))
                    {
                        return t;
                    }
                    return null;
                }
                return null;
            }
        }
        public static WoWUnit holyNovaUnit
        {
            get
            {
                int healthCheck = SD.myPrefs.HolyNovaHealthPercentD;
                if (groups.partyCount > 6) healthCheck = SD.myPrefs.HolyNovaHealthPercentR;

                int playerCount = SD.myPrefs.HolyNovaPlayerCountD;
                if (groups.partyCount > 6) playerCount = SD.myPrefs.HolyNovaPlayerCountR;

                if (groups.partyCount == 0)
                {
                    return null;
                }
                if (InProvingGrounds)
                {
                    var t = new List<WoWUnit>();
                    t = groups.PartyMembers.Where(p => p != null
                        && p.IsAlive
                        && p.InLineOfSight
                        && p.Distance <= 12
                        && p.HealthPercent <= healthCheck).ToList();
                    if (t.Count() >= playerCount)
                    {
                        return t.FirstOrDefault();
                    }
                    return null;
                }
                if (groups.partyCount > 0 && !InProvingGrounds)
                {
                    var t = new List<WoWPlayer>();
                    t = groups.PartyMembers.Where(p => p != null
                        && p.IsAlive
                        && p.InLineOfSight
                        && p.Distance <= 40
                        && p.HealthPercent <= healthCheck).Select(p => p.ToPlayer()).OrderBy(p => p.ToPlayer().HealthPercent).ToList();
                    if (t.Count() >= playerCount)
                    {
                        return t.FirstOrDefault();
                    }
                    return null;
                }
                return null;
            }
        }
        #endregion

        #region dispel
        public static WoWUnit dispelTargets
        {
            get
            {
                if (!SD.myPrefs.AutoDispel) return null;
                WoWUnit dispelTarget = ObjectManager.GetObjectsOfTypeFast<WoWUnit>().Where(p => p != null
                    && (p.Combat
                    && (p.IsTargetingMeOrPet || p.IsTargetingMyPartyMember || p.IsTargetingMyRaidMember))
                    && units.CanDispelMagic(p)
                    && p.Distance <= 30).OrderBy(p => p.Distance).FirstOrDefault();
                return dispelTarget != null ? dispelTarget : null;
            }
        }
        #endregion

        #region purify
        public static WoWUnit purifyPlayers
        {
            get
            {
                if (!SD.myPrefs.AutoDispel) return null;
                if (groups.partyCount == 0 && units.CanPurifyTarget(Me)) return Me;
                var t = groups.PartyMembers.Where(p => p != null
                        && p.IsAlive
                        && units.CanPurifyTarget(p)).OrderBy(p => p.HealthPercent).ThenBy(p => p.Distance).FirstOrDefault();
                return t != null ? t : null;
            }
        }
        #endregion

        #region trinkets
        public static DateTime _trinketTimer;
        private static bool CanUseEquippedItem(WoWItem item)
        {
            string itemSpell = Lua.GetReturnVal<string>("return GetItemSpell(" + item.Entry + ")", 0);
            if (string.IsNullOrEmpty(itemSpell))
                return false;
            return item.Usable && item.Cooldown <= 0;
        }
        public static bool needTrinket1
        {
            get
            {
                if (SD.myPrefs.Trinket1 == 0) return false;
                if (SD.myPrefs.Trinket1 == 1) //cooldown
                {
                    var Trinket1 = StyxWoW.Me.Inventory.Equipped.Trinket1;
                    if (Trinket1 != null
                        && CanUseEquippedItem(Trinket1))
                    {
                        Trinket1.Use();
                        Logging.Write(Colors.OrangeRed, "Using 1st Trinket");
                        return true;
                    }
                    return false;
                }
                if (SD.myPrefs.Trinket1 == 2) //low mana
                {
                    var Trinket1 = StyxWoW.Me.Inventory.Equipped.Trinket1;
                    if (Trinket1 != null
                        && CanUseEquippedItem(Trinket1)
                        && Me.ManaPercent <= SD.myPrefs.Trinket1ResourcesPercent)
                    {
                        Trinket1.Use();
                        Logging.Write(Colors.OrangeRed, "Using 1st Trinket");
                        return true;
                    }
                    return false;
                }
                if (SD.myPrefs.Trinket1 == 2) //low hp
                {
                    var Trinket1 = StyxWoW.Me.Inventory.Equipped.Trinket1;
                    if (Trinket1 != null
                        && CanUseEquippedItem(Trinket1)
                        && Me.HealthPercent <= SD.myPrefs.Trinket1ResourcesPercent)
                    {
                        Trinket1.Use();
                        Logging.Write(Colors.OrangeRed, "Using 1st Trinket");
                        return true;
                    }
                    return false;
                }
                if (SD.myPrefs.Trinket1 == 2) //crowdcontrolled
                {
                    var Trinket1 = StyxWoW.Me.Inventory.Equipped.Trinket1;
                    if (Trinket1 != null
                        && CanUseEquippedItem(Trinket1)
                        && units.IsCrowdControlledPlayer(Me))
                    {
                        Trinket1.Use();
                        Logging.Write(Colors.OrangeRed, "Using 1st Trinket");
                        return true;
                    }
                    return false;
                }
                return false;
            }
        }
        public static bool needTrinket2
        {
            get
            {
                if (SD.myPrefs.Trinket2 == 0) return false;
                if (SD.myPrefs.Trinket2 == 1) //cooldown
                {
                    var Trinket2 = StyxWoW.Me.Inventory.Equipped.Trinket2;
                    if (Trinket2 != null
                        && CanUseEquippedItem(Trinket2))
                    {
                        Trinket2.Use();
                        Logging.Write(Colors.OrangeRed, "Using 2nd Trinket");
                        return true;
                    }
                    return false;
                }
                if (SD.myPrefs.Trinket2 == 2) //low mana
                {
                    var Trinket2 = StyxWoW.Me.Inventory.Equipped.Trinket2;
                    if (Trinket2 != null
                        && CanUseEquippedItem(Trinket2)
                        && Me.ManaPercent <= SD.myPrefs.Trinket2ResourcesPercent)
                    {
                        Trinket2.Use();
                        Logging.Write(Colors.OrangeRed, "Using 2nd Trinket");
                        return true;
                    }
                    return false;
                }
                if (SD.myPrefs.Trinket2 == 2) //low hp
                {
                    var Trinket2 = StyxWoW.Me.Inventory.Equipped.Trinket2;
                    if (Trinket2 != null
                        && CanUseEquippedItem(Trinket2)
                        && Me.HealthPercent <= SD.myPrefs.Trinket2ResourcesPercent)
                    {
                        Trinket2.Use();
                        Logging.Write(Colors.OrangeRed, "Using 2nd Trinket");
                        return true;
                    }
                    return false;
                }
                if (SD.myPrefs.Trinket2 == 2) //crowdcontrolled
                {
                    var Trinket2 = StyxWoW.Me.Inventory.Equipped.Trinket2;
                    if (Trinket2 != null
                        && CanUseEquippedItem(Trinket2)
                        && units.IsCrowdControlledPlayer(Me))
                    {
                        Trinket2.Use();
                        Logging.Write(Colors.OrangeRed, "Using 2nd Trinket");
                        return true;
                    }
                    return false;
                }
                return false;
            }
        }
        #endregion

    }
}
